#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/sem.h>
#include <pthread.h>
#include <errno.h>
#define SYS_KEY 20000
union semun {
  int val;      /* value for SETVAL */
  struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
  unsigned short *array;  /* array for GETALL & SETALL */
  struct seminfo *__buf;  /* buffer for IPC_INFO */
  void *__pad;
};

void* put_thread(void*);
void* get_thread(void*);

int main(int argc, char* argv[]) {
  int id = semget(SYS_KEY, 1, IPC_CREAT|0666);
  pthread_t pt_put,pt_get;
  pthread_create(&pt_put, NULL, put_thread, NULL);
  pthread_create(&pt_get, NULL, get_thread, NULL);


  pthread_join(pt_put, NULL);
  pthread_join(pt_get, NULL);
  return 0;
}
void* put_thread(void*) {
  struct sembuf V;
  union semun arg;
  arg.val = 0;
  int id = semget(SYS_KEY, 1, 0);
  semctl(id, 1, SETVAL, arg);

  V.sem_num=0;
  V.sem_op=1;
  V.sem_flg=SEM_UNDO;
  int i = 0;
  while(1) {
    sleep(1);
    semop(id,&V,1);
    i++;
    printf("put [%d]!\n", i);
  }
  return NULL;
}

void* get_thread(void*) {
  struct sembuf P;
  struct sembuf V;
  union semun arg;
  arg.val = 0;
  int id = semget(SYS_KEY, 1, 0);
  semctl(id, 1, SETVAL, arg);

  P.sem_num=0;
  P.sem_op=-1;
  P.sem_flg=SEM_UNDO;

  struct timespec timeout;
  timeout.tv_sec = 1000;
  int i = 0;
  while(1) {
    semtimedop(id, &P,1, &timeout);
    //semop(id,&P,1);
    i++;
    printf("got [%d]!\n",i);
#if 0
    if( EAGAIN == errno) {
      printf("time out![%d]\n", errno);
    }
    else {
      i++;
      printf("got [%d]!\n", i);
    }
#endif
  }
  return NULL;
}
